const Koa = require("koa");
const app = new Koa();
const views = require("koa-views");
const json = require("koa-json");
const onerror = require("koa-onerror");
const bodyparser = require("koa-bodyparser");
const logger = require("koa-logger");
const dotenv = require("dotenv");
dotenv.config();
const user = require("./routes/user");
const menus = require("./routes/menus");
const role = require("./routes/role");
const home = require("./routes/home");
const banner = require("./routes/banner");
const koajwt = require("koa-jwt");
const morgan = require("koa-morgan");
const fs = require("fs");
const path = require("path");
const { errorModel, code } = require("./utils/stateModel");
//创建初始用户便于登录，（这样就不用手动再插入第一个用户,初次运行过后可以删除）
const { createFirstUser } = require("./controller/user");
createFirstUser({ username: "admin", password: "123456" });
// error handler
onerror(app);
//const user = require("./db/models/user")

// middlewares
app.use(
  bodyparser({ enableTypes: ["json", "form", "text"] })
);
app.use(json());
app.use(logger());
app.use(require("koa-static")(__dirname + "/public"));
app.use(
  views(__dirname + "/views", { extension: "pug" })
);

app.use(async (ctx, next) => {
  //日志设置token
  morgan.token("query", () => {
    let data = {};
    if (ctx.method == "POST") {
      data = ctx.request.body;
    } else {
      data = ctx.request.query;
    }
    console.log("【请求参数】:", JSON.stringify(data));
    return `${ctx.method} - ${new Date().getFullYear()}年${new Date().getMonth()}月${new Date().getDay()}日${new Date().getTime()}毫秒 - 请求参数: ${JSON.stringify(data)}`;
  });
  // 允许来自所有域名请求
  ctx.set("Access-Control-Allow-Origin", "*");
  // 设置所允许的HTTP请求方法
  ctx.set("Access-Control-Allow-Methods", "OPTIONS, GET, PUT, POST, DELETE");
  // 字段是必需的。它也是一个逗号分隔的字符串，表明服务器支持的所有头信息字段.
  ctx.set(
    "Access-Control-Allow-Headers",
    "x-requested-with, accept, origin, content-type,token"
  );
  if (ctx.method == "OPTIONS") {
    ctx.body = "";
    ctx.status = 204;
    return;
  }
  ctx.request.header.authorization = `Bearer ${ctx.request.header.token}`;
  await next().catch((err) => {
    // 捕捉下一个中间件错误
    if (err.status == 401) {
      //jwt token校验失败
      ctx.body = new errorModel("token校验失败", code.TOKEN_ERROR);
    } else {
      throw err;
    }
  });
});

if (process.env.NODE_ENV === "dev") {
  //记录自定义日志
  morgan.format("myrule", ":query");
  const writeStream = fs.createWriteStream(
    path.join(__dirname, "log", "access.log"),
    { flags: "a" }
  );
  app.use(
    morgan("myrule", {
      stream: writeStream,
    })
  );
} else {
  app.use(morgan("dev"));
}

// koajwt 中间件验证，unless 登录接口不需要
// /^\/api\/user\/login/,
// /^\/api\/user\/register/,
// /^\/api\/home\/bannerInfo/
app.use(
  koajwt({ secret: process.env.JWT_SECRET }).unless({
    path: [/^\/api/],
  })
);

// routes
app.use(user.routes(), user.allowedMethods());
app.use(menus.routes(), menus.allowedMethods());
app.use(role.routes(), menus.allowedMethods());
app.use(home.routes(), home.allowedMethods());
app.use(banner.routes(), banner.allowedMethods());

// error-handling
app.on("error", (err, ctx) => {
  console.error("server error", err, ctx);
});

module.exports = app;
